package com.hx.zhg.web.config;


import com.hx.zhg.constant.CacheNameConstant;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: redis配置
 */
@Configuration
@EnableCaching
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 300)
public class RedisConfig extends CachingConfigurerSupport {


    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder builder = new StringBuilder();
                builder.append(target.getClass().getCanonicalName());
                builder.append(method.getName());
                if (params != null) {
                    for (Object obj : params) {
                        builder.append(String.valueOf(obj));
                    }
                }
                return builder.toString();
            }
        };
    }

    @Bean("sessionCacheManager")
    public CacheManager sessionCacheManager(@SuppressWarnings("rawtypes") RedisTemplate busRedisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(busRedisTemplate);
        rcm.setDefaultExpiration(3600 * 24 * 30);//秒 缓存30天
        rcm.setUsePrefix(true);
        List<String> cacheNames = new ArrayList<>();
        cacheNames.add(CacheNameConstant.SESSION_CACHE);
        rcm.setCacheNames(cacheNames);
        return rcm;
    }

    @Primary
    @Bean("busCacheManager")
    public CacheManager busCacheManager(@SuppressWarnings("rawtypes") RedisTemplate busRedisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(busRedisTemplate);
        rcm.setDefaultExpiration(3600);//秒
        rcm.setUsePrefix(true);
        Map<String, Long> expiresMap = new HashMap<>();
        expiresMap.put(CacheNameConstant.BUSDATA_CACHE, 3600L);
        expiresMap.put(CacheNameConstant.USER_DATA_CACHE, 3600 * 36L);//用户数据缓存36小时
        expiresMap.put(CacheNameConstant.ACCESS_BLACK_CACHE, 300L);
        rcm.setExpires(expiresMap);
        List<String> cacheNames = new ArrayList<>();
        cacheNames.add(CacheNameConstant.BUSDATA_CACHE);
        cacheNames.add(CacheNameConstant.USER_DATA_CACHE);
        cacheNames.add(CacheNameConstant.ACCESS_BLACK_CACHE);
        rcm.setCacheNames(cacheNames);
        return rcm;
    }

    @Bean("accessTokenCacheManager")
    public CacheManager accessTokenCacheManager(@SuppressWarnings("rawtypes") RedisTemplate busRedisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(busRedisTemplate);
        rcm.setDefaultExpiration(3600 * 2);//accessToken保存2个小时
        rcm.setUsePrefix(true);
        List<String> cacheNames = new ArrayList<>();
        cacheNames.add(CacheNameConstant.ACCESS_TOKEN_CACHE);
        rcm.setCacheNames(cacheNames);
        return rcm;
    }

    @Bean
    public RedisTemplate<Object, Object> busRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(template.getStringSerializer());
        template.setValueSerializer(new JdkSerializationRedisSerializer(Thread.currentThread().getContextClassLoader()));
//        template.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class));
//        template.setValueSerializer(new FastJsonRedisSerializer<>(Object.class));
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 用于spring session，防止每次创建一个线程
     *
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor springSessionRedisTaskExecutor() {
        ThreadPoolTaskExecutor springSessionRedisTaskExecutor = new ThreadPoolTaskExecutor();
        springSessionRedisTaskExecutor.setCorePoolSize(8);
        springSessionRedisTaskExecutor.setMaxPoolSize(16);
        springSessionRedisTaskExecutor.setKeepAliveSeconds(10);
        springSessionRedisTaskExecutor.setQueueCapacity(1000);
        springSessionRedisTaskExecutor.setThreadNamePrefix("Spring session redis executor thread: ");
        return springSessionRedisTaskExecutor;
    }

}
